
// ContrastExperimentDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ContrastExperiment.h"
#include "ContrastExperimentDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CContrastExperimentDlg dialog




CContrastExperimentDlg::CContrastExperimentDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CContrastExperimentDlg::IDD, pParent)
	, m_nMaxMChordClusterSize(0)
	, m_nSearchStep(6)
	, m_nMinSearchRange(150)
	, m_nMaxSearchRange(900)
	, m_nSimpleNumber(10)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CContrastExperimentDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT12, m_nSearchStep);
	DDX_Text(pDX, IDC_EDIT10, m_nMinSearchRange);
	DDX_Text(pDX, IDC_EDIT11, m_nMaxSearchRange);
	DDX_Text(pDX, IDC_EDIT13, m_nSimpleNumber);
	DDV_MinMaxUInt(pDX, m_nSearchStep, 2, 20);
}

BEGIN_MESSAGE_MAP(CContrastExperimentDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_IMPORT_DATA, &CContrastExperimentDlg::OnBnClickedButtonImportData)
	ON_BN_CLICKED(IDC_BUTTON_IMPORT_SNAPSHOT, &CContrastExperimentDlg::OnBnClickedButtonImportSnapshot)
	ON_BN_CLICKED(IDC_BUTTON_INIT_MCHORD, &CContrastExperimentDlg::OnBnClickedButtonInitMchord)
	ON_BN_CLICKED(IDC_BUTTON_COMPARE, &CContrastExperimentDlg::OnBnClickedButtonCompare)
END_MESSAGE_MAP()


// CContrastExperimentDlg message handlers

BOOL CContrastExperimentDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	srand(GetTickCount());
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CContrastExperimentDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CContrastExperimentDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CContrastExperimentDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CContrastExperimentDlg::OnBnClickedButtonImportData()
{
	// TODO: Add your control notification handler code here
	CCalculator cCal;
#ifdef USE_VECTOR
	CFileDialog cFile(TRUE,"asc",NULL,6,"Vectro Data Files (*.asc)|*.asc||");
	if(cFile.DoModal()!=IDOK)
	{
		return;
	}
#else
	CFileDialog cFile(TRUE,"","Data.nil",6,"Nilsimsa Key Files (*.nil)|*.nil||");
	if(cFile.DoModal()!=IDOK)
	{
		return;
	}
#endif
	ifstream fin(cFile.GetPathName().GetString());
	if(fin)
	{
		this->SetWindowTextA(cFile.GetFileName().GetString());
		m_cKeyVector.clear();
		char Buffer[1024];
		while(fin.getline(Buffer,1024))
		{
			KEY tmp;
			if(tmp.FromString(Buffer))
			{
				m_cKeyVector.push_back(tmp);
			}
		}
		vector<unsigned int> cPos;
		GetRandomSequence(0,m_cKeyVector.size()-1,MCHORD_PIVOT_NO,cPos);
		for(unsigned i = 0;i<MCHORD_PIVOT_NO;i++)
		{
			CSnapshotItem tmp;
			tmp.m_cPivot = m_cKeyVector[cPos[i]];
			m_cMChordCluster.push_back(tmp);
			m_cMChordClusterMap.insert(make_pair(tmp.m_cPivot,i));
		}
		for(unsigned i = 0;i<m_cKeyVector.size();i++)
		{
			KEY & key = m_cKeyVector[i];
			unsigned nBeloned = 0;
			int nRadius = KEY::GetDistance(m_cMChordCluster[nBeloned].m_cPivot,key);
			for(unsigned j = 1;j<m_cMChordCluster.size();j++)
			{
				int nDis = KEY::GetDistance(key,m_cMChordCluster[j].m_cPivot);
				if(nDis<nRadius)
				{
					nBeloned = j;
					nRadius = nDis;
				}
			}
			m_cMChordCluster[nBeloned].m_nSize++;
			m_cMChordCluster[nBeloned].m_nRadius = max(nRadius,m_cMChordCluster[nBeloned].m_nRadius);
			m_nMaxMChordClusterSize = max(m_nMaxMChordClusterSize,m_cMChordCluster[nBeloned].m_nRadius);
		}
		for(unsigned i = 0;i<m_cMChordCluster.size();i++)
		{
			cCal.Add(m_cMChordCluster[i].m_nRadius);
		}
		cCal.Calculate();
		OutputDebugInfo("MChord Cluster Radius: %3lf, DEV: %3lf.",cCal.GetEven(),cCal.GetSDev());
		this->MessageBox("Success");
	}
	else
	{
		this->MessageBox("Open file error");
	}
}

void CContrastExperimentDlg::OnBnClickedButtonImportSnapshot()
{
	// TODO: Add your control notification handler code here
	CCalculator cCal;
	CFileDialog cFile(TRUE,"log",NULL,6,"Simulator Snapshot Files (*.log)|*.log||");
	if(cFile.DoModal()==IDOK)
	{
		ifstream fin(cFile.GetPathName().GetString());
		if(fin)
		{
			CSnapshotItem tmp;
			while(fin>>tmp)
			{
				m_cMKADNodeSet.push_back(tmp);
				cCal.Add(tmp.m_nRadius);
			/*	if(m_cMChordNodeCoordinateRangeSet.size()==0)
				{
					m_cMChordNodeCoordinateRangeSet.push_back(CSetEntry(0,MAX_CHORD_ID));
				}
				else
				{
					unsigned nPos = 0;
					do
					{
						nPos = RandUINT()%m_cMChordNodeCoordinateRangeSet.size();
					}while(m_cMChordNodeCoordinateRangeSet[nPos].m_nTo-m_cMChordNodeCoordinateRangeSet[nPos].m_nFrom<=2);
					int nStart =(m_cMChordNodeCoordinateRangeSet[nPos].m_nFrom+m_cMChordNodeCoordinateRangeSet[nPos].m_nTo)/2+1;
					int nEnd = m_cMChordNodeCoordinateRangeSet[nPos].m_nTo;
					m_cMChordNodeCoordinateRangeSet[nPos].m_nTo = nStart-1;
					m_cMChordNodeCoordinateRangeSet.push_back(CSetEntry(nStart,nEnd));
				}*/
			}
		//	sort(m_cMChordNodeCoordinateRangeSet.begin(),m_cMChordNodeCoordinateRangeSet.end());
			m_cMChordNodeCoordinateRangeSet.assign(m_cMKADNodeSet.size(),CSetEntry(0,0));
			float step = (float)MAX_CHORD_ID/m_cMKADNodeSet.size();
			for(unsigned i = 0;i<m_cMKADNodeSet.size();i++)
			{
				m_cMChordNodeCoordinateRangeSet[i].m_nFrom = D2I(step*i);
				m_cMChordNodeCoordinateRangeSet[i].m_nTo = D2I(step*(1+i))-1;
			}
			cCal.Calculate();		
			OutputDebugInfo("M-KAD Cluster Radius: %3lf, DEV: %3lf.",cCal.GetEven(),cCal.GetSDev());
		
			this->MessageBox("Success");
			return;
		}
	}
	this->MessageBox("Can not open File!");
	
}



void CContrastExperimentDlg::GetMChordRangeQuerySet(const KEY& key,const int nRange,unsigned int & nVisitNode,unsigned int & nInvolvedData)
{
	CRange cRes,cNode,cOverlap;
	GetMChordCooridinateRangeForRangeQuery(key,nRange,cRes);
	nVisitNode = 0;
	nInvolvedData = 0;
	for(vector<CSetEntry>::iterator it = m_cMChordNodeCoordinateRangeSet.begin();it!=m_cMChordNodeCoordinateRangeSet.end();++it)
	{
		cNode.Insert(*it);
	}
	cNode.GetOverlapRange(cRes,cOverlap);
	nVisitNode = cOverlap.m_cSet.size();
	for(CRange::SET::iterator it = cOverlap.m_cSet.begin();it!=cOverlap.m_cSet.end();++it)
	{
		nInvolvedData+=this->m_cMChordLocalDataCalculator[*it].m_nSize;
	}
}
void CContrastExperimentDlg::GetMKADRangeQuerySet(const KEY& key,const int nRange,unsigned int & nVisitNode,unsigned int & nInvolvedData)
{
	nVisitNode = 0;
	nInvolvedData = 0;
	const vector<CSnapshotItem>& cCluster = this->m_cMKADNodeSet;
	for( vector<CSnapshotItem>::const_iterator it = cCluster.begin();it!=cCluster.end();++it)
	{
		int nDis = KEY::GetDistance(key,it->m_cPivot);
		if(nDis<=nRange+it->m_nRadius)
		{
			nVisitNode++;
			nInvolvedData+=it->m_nSize;
		}
	}
};

void CContrastExperimentDlg::OnBnClickedButtonInitMchord()
{
	// TODO: Add your control notification handler code here
	for(vector<CSetEntry>::iterator it = m_cMChordNodeCoordinateRangeSet.begin();it!=m_cMChordNodeCoordinateRangeSet.end();++it)
	{
		m_cMChordLocalDataCalculator.insert(make_pair(*it,CMChordNode()));
	}
	for(vector<KEY>::iterator it = m_cKeyVector.begin();it!=m_cKeyVector.end();++it)
	{
		unsigned coordinate = this->GetMChordKey(*it);
		map<CSetEntry,CMChordNode,CSetEntry::less>::iterator it_successor = m_cMChordLocalDataCalculator.upper_bound(CSetEntry(coordinate,coordinate));
		if(it_successor==m_cMChordLocalDataCalculator.end())
		{
			it_successor=m_cMChordLocalDataCalculator.begin();
		}
		it_successor->second.m_nSize++;
		
	}
	this->MessageBox("Finish");	
	
}
void CContrastExperimentDlg::GetMChordCooridinateRangeForRangeQuery(const KEY& key,const int nRange,CRange& cRes)
{
	float C = (float)MAX_CHORD_ID/MCHORD_PIVOT_NO;
	float r = C/m_nMaxMChordClusterSize;
	for(unsigned i = 0;i<m_cMChordCluster.size();i++)
	{
		CSnapshotItem & cur = m_cMChordCluster[i];
		int nDis = KEY::GetDistance(cur.m_cPivot,key);
		if(nDis<=cur.m_nRadius+nRange)
		{
			int nStart = max(0,nDis-nRange);
			int nEnd = min(cur.m_nRadius,nDis+nRange);
			CSetEntry tmp((unsigned int)(nStart*r+i*C),(unsigned int)(nEnd*r+i*C));
			cRes.Insert(tmp);
		}
	}
}

void CContrastExperimentDlg::OnBnClickedButtonCompare()
{
	// TODO: Add your control notification handler code here
	this->UpdateData();
	ofstream fout("RawData.dat");
	if(!fout)
	{
		this->MessageBox("Open raw data file error");
		return;
	}
	for(unsigned nStep = 0;nStep<this->m_nSearchStep;nStep++)
	{
		unsigned nCurRange = this->m_nMinSearchRange+D2I((float)nStep*(m_nMaxSearchRange-m_nMinSearchRange)/(m_nSearchStep-1));
		CCalculator cCal1,cCal2,cCal3,cCal4;
		for(unsigned i = 0;i<m_nSimpleNumber;i++)
		{
			unsigned int nVisitNode = 0,nInvolvedData = 0;
			KEY & key = m_cKeyVector[RandUINT()%m_cKeyVector.size()];
			this->GetMKADRangeQuerySet(key,nCurRange,nVisitNode,nInvolvedData);
			cCal1.Add(nVisitNode);
			cCal2.Add(nInvolvedData);
			this->GetMChordRangeQuerySet(key,nCurRange,nVisitNode,nInvolvedData);
			cCal3.Add(nVisitNode);
			cCal4.Add(nInvolvedData);
		}
		cCal1.Calculate();
		cCal4.Calculate();
		cCal3.Calculate();
		cCal2.Calculate();
		fout<<nCurRange<<" "
			<<cCal1.GetEven()<<" "
			<<cCal2.GetEven()<<" "
			<<cCal3.GetEven()<<" "
			<<cCal4.GetEven()<<endl;
	}
	fout.close();
	this->MessageBox("Success");
}
